package com.easylinkin.linkappapi.childhospital.service.impl;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.easylinkin.linkappapi.childhospital.entity.*;
import com.easylinkin.linkappapi.childhospital.mapper.DormitoryManageBuildingMapper;
import com.easylinkin.linkappapi.childhospital.mapper.DormitoryManageFloorMapper;
import com.easylinkin.linkappapi.childhospital.mapper.DormitoryManageRoomMapper;
import com.easylinkin.linkappapi.childhospital.service.DormitoryManageService;
import com.easylinkin.linkappapi.childhospital.vo.DormitoryManage;
import com.easylinkin.linkappapi.childhospital.mapper.DormitoryManageUserMapper;
import com.easylinkin.linkappapi.childhospital.vo.DormitoryHistoryUserVo;
import com.easylinkin.linkappapi.childhospital.vo.DormitoryManageSelectVo;
import com.easylinkin.linkappapi.childhospital.vo.IDCardVo;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.Assert;
import site.morn.boot.rest.RestPage;
import site.morn.rest.RestPageable;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassNameDormitoryManageImpl
 * @Description
 * @YanQiang
 * @Date 2024/3/18 17:55
 * @Version 1.0
 */

@Slf4j
@Service("dormitoryManageService")
public class DormitoryManageServiceImpl extends ServiceImpl<DormitoryManageFloorMapper, DormitoryManageFloor> implements DormitoryManageService {

    @Resource
    LinkappUserContextProducer linkappUserContextProducer;

    @Resource
    private DormitoryManageRoomMapper dormitoryManageRoomMapper;

    @Resource
    private DormitoryManageUserMapper dormitoryManageUserMapper;

    @Resource
    private DormitoryManageBuildingMapper dormitoryManageBuildingMapper;

    @Resource
    private DormitoryManageFloorMapper dormitoryManageFloorMapper;

    @Override
    public List<DormitoryManage> selectDormitoryManage(DormitoryManage dormitoryManage) {
        List<DormitoryManage> dormitoryManages = baseMapper.selectDormitoryManage(dormitoryManage);
        Map<String, List<DormitoryManage>> dorManageMap = dormitoryManages.stream().collect(Collectors.groupingBy(DormitoryManage::getBuildingName));
        List<DormitoryManage> dormitoryManageList = new ArrayList<>();
        if (ObjectUtils.isNotEmpty(dorManageMap)) {
            for (Map.Entry<String, List<DormitoryManage>> dorManageEntry : dorManageMap.entrySet()) {
                DormitoryManage dorManage = new DormitoryManage();
                dorManage.setBuildingName(dorManageEntry.getKey());
                List<DormitoryManage> value = dorManageEntry.getValue();
                Integer roomNumber = 0;
                for (DormitoryManage dormitory : value) {
                    roomNumber = dormitory.getRoomNumber();
                }
                dorManage.setRoomNumber(roomNumber);
                dormitoryManageList.add(dorManage);
            }
        }
        return dormitoryManageList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertOrUpdateDormitoryManage(List<DormitoryManageFloor> dorFloorList) {
        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        // 过滤出新增宿舍集合
        List<DormitoryManageFloor> newDormitoryManageFloors = dorFloorList.stream().filter(dor -> StringUtils.isAllEmpty(dor.getId())).collect(Collectors.toList());
        // 过滤出修改宿舍集合
        List<DormitoryManageFloor> oldDormitoryManageFloors = dorFloorList.stream().filter(dor -> StringUtils.isNotEmpty(dor.getId())).collect(Collectors.toList());
        List<DormitoryManageRoom> newDormitoryRoomList = new ArrayList<>();
        for (DormitoryManageFloor floor : newDormitoryManageFloors) {
            String floorId = IdUtil.simpleUUID();
            floor.setId(floorId);
            floor.setCreator(tenantId);
            floor.setCreateTime(new Date());
            floor.setModifier(tenantId);
            floor.setModifyTime(new Date());
            if (!CollectionUtils.isEmpty(floor.getDormitoryManageRoomList())) {
                List<DormitoryManageRoom> dormitoryManageRoomList = floor.getDormitoryManageRoomList();
                for (DormitoryManageRoom room : dormitoryManageRoomList) {
                    String roomId = IdUtil.simpleUUID();
                    room.setId(roomId);
                    room.setFloorId(floorId);
                    room.setCreator(tenantId);
                    room.setCreateTime(new Date());
                    room.setModifier(tenantId);
                    room.setModifyTime(new Date());
                }
                newDormitoryRoomList.addAll(dormitoryManageRoomList);
            }
        }
        baseMapper.insertBatch(newDormitoryManageFloors);
        dormitoryManageRoomMapper.insertBatch(newDormitoryRoomList);
    }

    /**
     * 导航栏查询条件
     *
     * @param entity
     * @return
     */
    @Override
    public List<DormitoryManageBuilding> getDormitoryInfo(DormitoryManageSelectVo entity) {
        LambdaQueryWrapper<DormitoryManageBuilding> queryWrapper = Wrappers.lambdaQuery();
        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        List<DormitoryManageBuilding> buildings = null;
        if (StringUtils.isEmpty(entity.getBuildingId())) {
            buildings = dormitoryManageBuildingMapper.selectList(queryWrapper.eq(DormitoryManageBuilding::getTenantId, tenantId).orderByAsc(DormitoryManageBuilding::getBuildingName));
        } else {
            queryWrapper.eq(DormitoryManageBuilding::getId, entity.getBuildingId()).eq(DormitoryManageBuilding::getTenantId, tenantId).orderByAsc(DormitoryManageBuilding::getBuildingName);
            buildings = dormitoryManageBuildingMapper.selectList(queryWrapper);
            if (buildings.size() > 0) {
                LambdaQueryWrapper<DormitoryManageFloor> floorWrapper = Wrappers.lambdaQuery();
                floorWrapper.eq(DormitoryManageFloor::getBuildingId, entity.getBuildingId()).orderByAsc(DormitoryManageFloor::getFloorName);
                List<DormitoryManageFloor> manageFloors = dormitoryManageFloorMapper.selectList(floorWrapper);
                if (manageFloors.size() > 0) {
                    buildings.get(0).setDormitoryManageFloorsList(manageFloors);
                }
            }
        }
        return buildings;
    }

    /**
     * 获取宿舍信息-树形结构
     *
     * @param entity
     * @return
     */
    @Override
    public List<DormitoryManageBuilding> getDormitoryDetail(DormitoryManageSelectVo entity) {
        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        //房间汇总
        List<DormitoryDetail> list = dormitoryManageBuildingMapper.getDormitoryDetail(entity, tenantId);
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        //住宿人员汇总
        List<String> roomIds = list.stream().map(DormitoryDetail::getRoomId).filter(StringUtils::isNotEmpty).collect(Collectors.toList());
        List<DormitoryManageUser> userList = dormitoryManageBuildingMapper.getDormitoryUser(roomIds);

        Set<DormitoryManageBuilding> building = new HashSet<>();
        Set<DormitoryManageFloor> floor = new HashSet<>();
        Set<DormitoryManageRoom> room = new HashSet<>();
        list.forEach(e -> {
            building.add(new DormitoryManageBuilding(e.getId(), e.getBuildingName()));
            if (StringUtils.isNotEmpty(e.getFloorId())) {
                floor.add(new DormitoryManageFloor(e.getFloorId(), e.getFloorName(), e.getId(), e.getBuildingName()));
            }
            if (StringUtils.isNotEmpty(e.getRoomId())) {
                room.add(new DormitoryManageRoom(e.getRoomId(), e.getFloorId(), e.getRoomName(), e.getRoomNumber(), e.getRoomUsedNumber(), e.getRoomLabel(), e.getSex(), e.getRoomStatus()));
            }
        });
        room.forEach(e -> {
            e.setTotal(e.getRoomNumber());
            e.setCurrent(e.getRoomUsedNumber());
            userList.forEach(r -> {
                if (e.getId().equals(r.getRoomId())) {
                    e.getDormitoryManageUserList().add(r);
                }
            });
        });
        floor.forEach(f -> room.stream().filter(e -> f.getId().equals(e.getFloorId())).forEach(e -> {
            f.setTotal(f.getTotal() + e.getTotal());
            f.setCurrent(f.getCurrent() + e.getCurrent());
            e.getDormitoryManageUserList().sort(Comparator.comparing(DormitoryManageUser::getCreateTime));
            f.getDormitoryManageRoomList().add(e);
        }));
        building.forEach(b -> floor.stream().filter(e -> b.getId().equals(e.getBuildingId())).forEach(e -> {
            b.setTotal(b.getTotal() + e.getTotal());
            b.setCurrent(b.getCurrent() + e.getCurrent());
            b.getDormitoryManageFloorsList().add(e);
        }));
        List<DormitoryManageBuilding> buildings = new ArrayList<>(building);
        buildings.sort(Comparator.comparing(DormitoryManageBuilding::getBuildingName));
        buildings.forEach(b -> {
            b.getDormitoryManageFloorsList().sort(Comparator.comparing(DormitoryManageFloor::getFloorName));
            b.getDormitoryManageFloorsList().forEach(f -> {
                f.getDormitoryManageRoomList().sort(Comparator.comparingInt(r -> Integer.parseInt(r.getRoomName().replaceAll("\\D+", ""))));//处理中文排序问题
            });
        });
        return buildings;
    }

    /**
     * 获取宿舍历史信息
     *
     * @param restPage
     * @return
     */
    @Override
    public Page<DormitoryManageUser> getDormitoryUserHistory(RestPage<DormitoryHistoryUserVo> restPage) {
        RestPageable pageable = restPage.getPageable();
        DormitoryHistoryUserVo model = restPage.getModel();
        Page page = new Page(pageable.getPage(), pageable.getSize());
        List<DormitoryManageUser> checkHistory = dormitoryManageBuildingMapper.getCheckHistoryUser(model.getRoomId(), model.getKeywords(), page);
        checkHistory.forEach(this::replaceIDCard);
        page.setRecords(checkHistory);
        return page;
    }

    /**
     * 退宿
     *
     * @param userId
     */
    @Override
    @Transactional
    public void dormitoryCheckOut(String userId) {
        LambdaQueryWrapper<DormitoryManageUser> floorWrapper = Wrappers.lambdaQuery();
        DormitoryManageUser user = dormitoryManageUserMapper.selectOne(floorWrapper.eq(DormitoryManageUser::getId, userId));
        UpdateWrapper<DormitoryManageUser> eq = new UpdateWrapper<DormitoryManageUser>().set("status", 0).set("out_time", new Date()).eq("id", userId);
        dormitoryManageUserMapper.update(user, eq);
        dormitoryManageRoomMapper.updateRoomUsedNumber(user.getRoomId(), -1);
    }

    /**
     * 获取宿舍人员信息
     *
     * @param roomId
     * @param keywords
     * @return
     */
    @Override
    public Map<String, Object> getDormitoryUserInfo(String roomId, String keywords) {
        Map<String, Object> map = new HashMap<>();
        LambdaQueryWrapper<DormitoryManageRoom> floorWrapper = Wrappers.lambdaQuery();
        floorWrapper.eq(DormitoryManageRoom::getId, roomId);
        //宿舍信息
        DormitoryManageRoom room = dormitoryManageRoomMapper.selectOne(floorWrapper);
        Assert.notNull(room, "该房间不存在");
        room.setTotal(room.getRoomNumber());
        room.setCurrent(room.getRoomUsedNumber());
        //入住总数
        int countHistory = dormitoryManageBuildingMapper.getCountHistory(roomId);
        List<DormitoryManageUser> userInfo = dormitoryManageBuildingMapper.getCurrentUser(roomId);
        userInfo.sort(Comparator.comparing(DormitoryManageUser::getCreateTime));
        userInfo.forEach(this::replaceIDCard);

        map.put("room", room);
        map.put("current", userInfo.size());
        map.put("history", countHistory);
        map.put("checkIn", userInfo);
        return map;
    }

    /**
     * 隐藏身份证号
     *
     * @param e
     */
    public void replaceIDCard(DormitoryManageUser e) {
        String identificationNumber = e.getIdentificationNumber();
        if (identificationNumber != null) {
            if (identificationNumber.length() == 15) {
                String replaced = identificationNumber.replaceAll("(\\d{4})\\d{7}(\\d{4})", "$1******$2");
                e.setIdentificationNumberHidden(replaced);
            }
            if (identificationNumber.length() == 18) {
                String replaced = identificationNumber.replaceAll("(\\d{4})\\d{10}(\\d{4})", "$1***********$2");
                e.setIdentificationNumberHidden(replaced);
            }
        }
    }

    /**
     * 插入宿舍信息
     *
     * @param json
     * @description 需求：一次性完成新增、修改、删除-所有楼栋、楼层、宿舍信息，如果后续需求变更，建议优化
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertDormitory(Map<String, Object> json) {
        Assert.notNull(json.get("json"), "参数不能为空");
        String string = json.get("json").toString();
        String tenantId = linkappUserContextProducer.getNotNullCurrent().getTenantId();
        List<DormitoryManageBuilding> build = JSON.parseArray(string, DormitoryManageBuilding.class);
        build.forEach(e -> {
            Assert.isTrue(StringUtils.isNotEmpty(e.getBuildingName()),"建筑名称不能为空");
            List<DormitoryManageFloor> floorsList = e.getDormitoryManageFloorsList();
            if (!CollectionUtils.isEmpty(floorsList)) {
                floorsList.forEach(f -> {
                    Assert.isTrue(StringUtils.isNotEmpty(f.getFloorName()),"楼层名称不能为空");
                    if (!CollectionUtils.isEmpty(f.getDormitoryManageRoomList())) {
                        f.getDormitoryManageRoomList().forEach(r -> {
                            Assert.isTrue(StringUtils.isNotEmpty(r.getRoomName()),"房间名称不能为空");
                            //新增、修改、删除房间  0：删除，1：修改，2：新增
                            switch (r.getFlagStatus()) {
                                case 0:
                                    LambdaQueryWrapper<DormitoryManageUser> queryWrapper = Wrappers.lambdaQuery();
                                    List<DormitoryManageUser> userList = dormitoryManageUserMapper.selectList(queryWrapper.eq(DormitoryManageUser::getRoomId, r.getId()).eq(DormitoryManageUser::getStatus, 1));
                                    if (CollectionUtils.isEmpty(userList)) {//为空则删除
                                        dormitoryManageRoomMapper.deleteById(r.getId());
                                    }
                                    break;
                                case 1:
                                    r.setModifyTime(new Date());
                                    r.setModifier(tenantId);
                                    dormitoryManageRoomMapper.updateById(r);
                                    break;
                                case 2:
                                    r.setCreateTime(new Date());
                                    r.setCreator(tenantId);
                                    r.setTenantId(tenantId);
                                    r.setFloorId(f.getId());
                                    dormitoryManageRoomMapper.insert(r);
                                    break;
                            }
                        });
                    }
                    //新增、修改、删除楼层  0：删除，1：修改，2：新增
                    switch (f.getFlagStatus()) {
                        case 0:
                            LambdaQueryWrapper<DormitoryManageRoom> queryWrapper = Wrappers.lambdaQuery();
                            List<DormitoryManageRoom> roomList = dormitoryManageRoomMapper.selectList(queryWrapper.eq(DormitoryManageRoom::getFloorId, f.getId()));
                            if (CollectionUtils.isEmpty(roomList)) {//为空则删除
                                dormitoryManageFloorMapper.deleteById(f.getId());
                            }
                            break;
                        case 1:
                            f.setBuildingName(e.getBuildingName());
                            f.setModifyTime(new Date());
                            f.setModifier(tenantId);
                            dormitoryManageFloorMapper.updateById(f);
                            break;
                        case 2:
                            f.setBuildingName(e.getBuildingName());
                            f.setCreateTime(new Date());
                            f.setCreator(tenantId);
                            f.setTenantId(tenantId);
                            f.setBuildingId(e.getId());
                            dormitoryManageFloorMapper.insert(f);
                            break;
                    }
                });
            }
            //新增、修改、删除楼栋  0：删除，1：修改，2：新增
            switch (e.getFlagStatus()) {
                case 0:
                    LambdaQueryWrapper<DormitoryManageFloor> queryWrapper = Wrappers.lambdaQuery();
                    List<DormitoryManageFloor> floorList = dormitoryManageFloorMapper.selectList(queryWrapper.eq(DormitoryManageFloor::getBuildingId, e.getId()));
                    if (CollectionUtils.isEmpty(floorList)) {//为空则删除
                        dormitoryManageBuildingMapper.deleteById(e.getId());
                    }
                    break;
                case 1:
                    e.setModifyTime(new Date());
                    e.setModifier(tenantId);
                    dormitoryManageBuildingMapper.updateById(e);
                    break;
                case 2:
                    e.setCreateTime(new Date());
                    e.setCreator(tenantId);
                    e.setTenantId(tenantId);
                    dormitoryManageBuildingMapper.insert(e);
                    break;
            }
        });
    }

    /**
     * 实名认证校验
     *
     * @param entity
     * @return
     */
    @Override
    public EmpUserBase realNameCheck(IDCardVo entity) {
        EmpUserBase userBase = dormitoryManageUserMapper.realNameCheck(entity);
        if (userBase == null){
            return null;
        }
        userBase.setAge(calculateAge(userBase.getCard()));
        return userBase;
    }

    /**
     * 根据身份证号获取年龄
     *
     * @param idNumber 身份证号
     * @return 年龄
     */
    private static int calculateAge(String idNumber) {
        int birthYear = Integer.parseInt(idNumber.substring(6, 10));
        int birthMonth = Integer.parseInt(idNumber.substring(10, 12));
        int birthDay = Integer.parseInt(idNumber.substring(12, 14));
        Calendar currentCalendar = Calendar.getInstance();
        int currentYear = currentCalendar.get(Calendar.YEAR);
        int currentMonth = currentCalendar.get(Calendar.MONTH) + 1;
        int currentDay = currentCalendar.get(Calendar.DAY_OF_MONTH);
        int age = currentYear - birthYear;
        if (birthMonth > currentMonth || (birthMonth == currentMonth && birthDay > currentDay)) {
            age--;
        }
        return age;
    }

    /**
     * 入住
     *
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean checkIn(IDCardVo entity) {
        EmpUserBase userBase = dormitoryManageUserMapper.realNameCheck(entity);
        Assert.notNull(userBase, "未查询到该用户");
        LambdaQueryWrapper<DormitoryManageUser> lambda = Wrappers.lambdaQuery();
        lambda.eq(DormitoryManageUser::getIdentificationNumber, userBase.getCard()).eq(DormitoryManageUser::getStatus, 1);
        List<DormitoryManageUser> userList = dormitoryManageUserMapper.selectList(lambda);
        Assert.isTrue(CollectionUtils.isEmpty(userList), "该用户已入住");
        DormitoryManageUser user = new DormitoryManageUser();
        user.setId(UUID.randomUUID().toString());
        user.setUserName(userBase.getName());
        user.setIdentificationNumber(userBase.getCard());
        user.setRoomId(entity.getRoomId());
        user.setUserAge(entity.getAge());
        user.setOrganization(userBase.getCompanyName());
        user.setImage(userBase.getPhoto());
        user.setSmoking(entity.getSmoking());
        user.setSnore(entity.getSnore());
        user.setSex(userBase.getGender());
        user.setCreateTime(new Date());
        user.setTenantId(userBase.getEmpUid());
        user.setStatus(1);
        user.setWorkType(userBase.getWorkType());
        dormitoryManageUserMapper.insert(user);
        //修改房间入住信息
        dormitoryManageRoomMapper.updateRoomUsedNumber(entity.getRoomId(), 1);
        return true;
    }

    /**
     * 退住
     *
     * @param userId
     * @param roomId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void checkOut(String userId, String roomId) {
        dormitoryManageUserMapper.updateCheckStatusById(userId);
        dormitoryManageRoomMapper.updateRoomUsedNumber(roomId, -1);
    }

    /**
     * app首页统计
     *
     * @param floorId
     * @return
     */
    @Override
    public Map<String, Object> appCount(String floorId) {
        Map<String, Object> map = new HashMap<>();
        if (StringUtils.isBlank(floorId)) {
            int buildCount = dormitoryManageBuildingMapper.selectCount(null);
            map.put("buildCount", buildCount);
            int integer = dormitoryManageFloorMapper.selectCount(null);
            map.put("floorCount", integer == 0 ? 0 : dormitoryManageFloorMapper.selectFloorCount());
        }

        Map<String, Object> room = dormitoryManageRoomMapper.selectRoomCount(floorId);
        int roomCount = Integer.parseInt(room.get("roomCount").toString());//总房间数
        int bedCount = Integer.parseInt(room.get("bedCount").toString());//总床位数

        Map<String, Object> user = dormitoryManageUserMapper.selectUseRoomAndUser(floorId);
        int userCount = Integer.parseInt(user.get("userCount").toString());//入住人数/床数
        int roomUse = Integer.parseInt(user.get("roomCount").toString());//使用的房间数

        map.put("roomCount", roomUse + "/" + roomCount);
        map.put("userCount", userCount + "/" + bedCount);
        return map;
    }

    /**
     * app根据楼层查房间
     *
     * @param floorId
     * @return
     */
    @Override
    public List<DormitoryManageRoom> appFindRoomUserByFloorId(String floorId) {
        List<DormitoryManageRoom> list = dormitoryManageRoomMapper.selectList(new QueryWrapper<DormitoryManageRoom>().eq("floor_id", floorId).orderByAsc("room_name"));
        for (DormitoryManageRoom room : list) {
            room.setTotal(room.getRoomNumber());
            room.setCurrent(room.getRoomUsedNumber());
            List<DormitoryManageUser> userList = dormitoryManageUserMapper.selectList(new QueryWrapper<DormitoryManageUser>().eq("room_id", room.getId()).eq("status", 1).orderByAsc("create_time"));
            if (!CollectionUtils.isEmpty(userList)) {
                userList.forEach(this::replaceIDCard);
                room.setDormitoryManageUserList(userList);
            }
        }
        return list;
    }
}
